<html>
	<head>
	    
	    <title>Bezier Curve</title>
	    <style>
            body {
                margin: 25px;
            }
	        canvas {
	            border: 1px solid black;
	        }
	        
            #point-info th,
            #point-info td
	        {
	            width: 50px;
	        }
	    </style>
	    
	    <script>
            var $id     = function(id) { return document.getElementById(id); };
            var $query  = function(q) { return document.querySelector(q); };
            var $queryAll   = function(q) { return document.querySelectorAll(q); };
	    </script>
	    <script type="text/javascript" src="bezier-curve.js"></script>
	    
	    <script>

	        
            
	    </script>
	    
	    <script>
	        var Point = function(x, y, radius, name)
	        {
                this.x = x || 0;
                this.y = y || 0;
                this.radius = radius || 5;
                this.name = name || "P";
                return this;
	        };
	        
	        Point.leap = function(p0, p1, amount)
	        {
	            return new Point(
                    Math.leap(p0.x, p1.x, amount),
                    Math.leap(p0.y, p1.y, amount),
                    p0.radius
	            );
	        };
	        
	        Point.prototype = {
	            draw: function(c)
	            {
                    c.beginPath();
                    c.arc(this.x, this.y, this.radius, 0, Math.PI*2, true);
                    c.fill();
                    
                    c.font = '16px "Meiryo", sans-serif';
                    c.fillText(this.name, this.x+5, this.y-5);
	            },
	            
	            isHit: function(x, y)
	            {
	                return (this.x-x)*(this.x-x)+(this.y-y)*(this.y-y)<this.radius*this.radius;
	            }
	        };
	        
	        var getMousePos = function(e)
	        {
	            var rect = e.target.getBoundingClientRect();
	            return {
                    x: e.clientX - rect.left,
                    y: e.clientY - rect.top
	            };
	        };
	        
	    </script>
	    
	    <script>
            var p0 = new Point(30, 30, 5, "P0");
            var p1 = new Point(50, 370, 5, "P1");
            var p2 = new Point(350, 30, 5, "P2");
            var p3 = new Point(370, 370, 5, "P3");
            var pList = [
                p0, p1, p2, p3
            ];
            var holdPoint = null;
	        
	        window.onload = function()
	        {
	            /*
                console.log( BezierCurve.solveCubic(1,-6,11,-6, 0) );
                console.log( BezierCurve.solveCubic(1,-6,11,-6, 1) );
                console.log( BezierCurve.solveCubic(1,-6,11,-6, 2) );
                console.log( BezierCurve.solveCubic(1,-6,11,-6, 3) );
                console.log( BezierCurve.solveCubic(1,-6,11,-6, 4) );
                
	            for (var i=1; i<10; ++i) {
	                var x = i*0.1;
                    var t = BezierCurve.toT(x, 0, 0, 1, 1);
                    var y = BezierCurve.calc(t, 0, 0, 1, 1);
                    console.log(t, x, y);
	            }
	            */
                
                var canvas = $id("c");
                
                // 
                // マウスダウンイベントを登録
                // 
                canvas.addEventListener("mousedown", function(e){
                    var mousePos = getMousePos(e);
                    for (var i=0; i<pList.length; ++i) {
                        var p = pList[i];
                        if (p.isHit(mousePos.x, mousePos.y)) {
                            holdPoint = p;
                        }
                    }
                }, false);
                
                // 
                // マウス移動イベントを登録
                // 
                canvas.addEventListener("mousemove", function(e){
                    var mousePos = getMousePos(e);
                    
                    var isHit = false;
                    for (var i=0; i<pList.length; ++i) {
                        var p = pList[i];
                        if (p.isHit(mousePos.x, mousePos.y)) {
                            isHit = true;
                        }
                    }
                    this.style.cursor = (isHit)?"hand":"";
                    
                    if (holdPoint) {
                        holdPoint.x = mousePos.x;
                        holdPoint.y = mousePos.y;
                        draw();
                        refreshPointInfo();
                    }
                    
                }, false);
                
                // 
                // マウスアップイベントを登録
                // 
                canvas.addEventListener("mouseup", function(e){
                    holdPoint = null;
                }, false);
                
                // 
                // 全ての input 要素の value 変更時イベントを登録
                // 
	            var input_list = $queryAll("input");
	            for (var i=0; i<input_list.length; ++i) {
	                var input = input_list[i];
	                input.addEventListener("change", function(){ draw(); }, false);
	            }
	            
	            // 描画
                draw();
                refreshPointInfo();
	        };
	        
	        var draw = function()
	        {
                var canvas = $id("c");
                var context = canvas.getContext("2d");
                
                context.clearRect(0, 0, 400, 400);
                
                // 
                // ネイティブ描画
                // 
                if ($query("#native").checked == true) {
                    context.beginPath();
                    context.moveTo(p0.x, p0.y);
                    context.bezierCurveTo(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);
                    context.strokeStyle = "black";
                    context.stroke();
                }
                
                // 
                // アプリケーション描画
                // 
                if ($query("#app").checked == true) {
                    context.beginPath();
                    context.moveTo(p0.x, p0.y);
                    var divit = 100;
                    for (var i=0; i<=divit; ++i) {
                        context.lineTo(
                            BezierCurve.calc(i/divit, p0.x, p1.x, p2.x, p3.x),
                            BezierCurve.calc(i/divit, p0.y, p1.y, p2.y, p3.y)
                            );
                    }
                    context.strokeStyle = "black";
                    context.stroke();
                }
                
                // ４点を表示
                context.fillStyle = "black";
                for (var i=0; i<pList.length; ++i) { pList[i].draw(context); }
                
                // ガイド表示
                if ($query("#guide").checked == true) { drawGuide(context); }
	        };
	        
	        var drawPoint = function(c, p, radius)
	        {
	            radius = radius || 5;
                c.beginPath();
	            c.arc(p.x, p.y, radius, 0, Math.PI*2, true);
                c.fill();
	        };
	        
	        var drawLine = function(c, start, end)
	        {
                c.beginPath();
                c.moveTo(start.x, start.y);
                c.lineTo(end.x, end.y);
                c.stroke();
	        };
	        
	        var drawGuide = function(context)
	        {
                context.strokeStyle = "red";
                drawLine(context, p0, p1);
                drawLine(context, p1, p2);
                drawLine(context, p2, p3);
                
                var t = $id("t").value;
                var p4 = Point.leap(p0, p1, t); p4.name = "p4";
                var p5 = Point.leap(p1, p2, t); p5.name = "p5";
                var p6 = Point.leap(p2, p3, t); p6.name = "p6";
                
                context.strokeStyle = "green";
                context.fillStyle = "green";
                p4.draw(context);
                p5.draw(context);
                p6.draw(context);
                drawLine(context, p4, p5);
                drawLine(context, p5, p6);
                
                var p7 = Point.leap(p4, p5, t); p7.name = "p7";
                var p8 = Point.leap(p5, p6, t); p8.name = "p8";
                context.strokeStyle = "blue";
                context.fillStyle = "blue";
                drawLine(context, p7, p8);
                p7.draw(context);
                p8.draw(context);
                
                var p9 = new Point( t*p8.x + (1-t)*p7.x, t*p8.y + (1-t)*p7.y, 5, "p9" );
                context.fillStyle = "gold";
                p9.draw(context);
	        };
	        
	        var refreshPointInfo = function()
	        {
	            var point_info = $id("point-info");
	            var e_pointList = point_info.getElementsByClassName("point");
	            
	            for (var i=0; i<e_pointList.length; ++i) {
                    var e_x = e_pointList[i].getElementsByClassName("point-x")[0];
                    var e_y = e_pointList[i].getElementsByClassName("point-y")[0];
                    e_x.innerHTML = pList[i].x;
                    e_y.innerHTML = pList[i].y;
	            }
	        };
	        
	        
	    </script>
	    
	</head>
	<body>
	    <h1>Bezier Curve</h1>
	    <canvas id="c" width="400" height="400"></canvas>
	    <form>
            <label><input type="checkbox" id="native" checked />Native</label>
            <label><input type="checkbox" id="app" />Application</label>
            <label><input type="checkbox" id="guide" checked />Guide</label>
            <br />
            <label>t : <input type="range" id="t" value=0.5 max=1 step=0.01 /></label>
            <br />
            
            <table id="point-info" border=1>
                <tr>
                    <th></th>
                    <th>x</th>
                    <th>y</th>
                </tr>
                <tr class="point">
                    <th>p0</th>
                    <td class="point-x">50</td>
                    <td class="point-y">100</td>
                </tr>
                <tr class="point">
                    <th>p1</th>
                    <td class="point-x">50</td>
                    <td class="point-y">100</td>
                </tr>
                <tr class="point">
                    <th>p2</th>
                    <td class="point-x">50</td>
                    <td class="point-y">100</td>
                </tr>
                <tr class="point">
                    <th>p3</th>
                    <td class="point-x">50</td>
                    <td class="point-y">100</td>
                </tr>
            </table>
	    </form>
	    
	</body>
</html>




















